/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package modules.estoque.validation;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Clezio
 */
public class Validation {

    private static Validation instance;
    private List<Error> erros;

    private Validation() {
    }

    public synchronized static Validation getInstance() {
        if (instance == null) {
            instance = new Validation();
        }
        return instance;
    }

    public void valid(Object obj) {
        if(erros == null){
            erros = new ArrayList<Error>();
        }
        try {
            Class<?> classe = obj.getClass();
            for (Field f : classe.getDeclaredFields()) {
                f.setAccessible(true);
                Class<?> type = f.getType();
                if (f.isAnnotationPresent(Required.class)) {
                    Required required = f.getAnnotation(Required.class);
                    if (!type.isPrimitive()) {
                        if (type.getSimpleName().equals(String.class.getSimpleName())) {
                            if (f.get(obj) == null || f.get(obj).equals("")) {
                                addErros(new Error(f.getName(), required.message()));
                            }
                        }else if (type.getSimpleName().equals(BigDecimal.class.getSimpleName())) {
                            if (f.get(obj) == null) {
                                addErros(new Error(f.getName(), required.message()));
                            }
                        }else if (type.getSimpleName().equals(Set.class.getSimpleName())) {
                            Set set = (Set) f.get(obj);
                            if(set.size() < 1){
                                addErros(new Error(f.getName(), required.message()));
                            }
                        }else{
                            if (f.get(obj) == null) {
                                addErros(new Error(f.getName(), required.message()));
                            }
                        }
                    }
                }

                if (f.isAnnotationPresent(Min.class)) {
                    Min min = f.getAnnotation(Min.class);
                    if (!type.isPrimitive()) {
                        if (type.getSimpleName().equals(BigDecimal.class.getSimpleName())) {
                            if (f.get(obj) != null) {
                                BigDecimal bigDecimal = (BigDecimal) f.get(obj);
                                if(bigDecimal.doubleValue() < min.value()){
                                    addErros(new Error(f.getName(), min.message()));
                                }
                            }
                        }
                    }else{
                        if((new Double(""+f.get(obj))) < min.value()){
                            addErros(new Error(f.getName(), min.message()));
                        }
                    }
                }
            }
        } catch (Exception ex) {
            Logger.getLogger(Validation.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void addErros(Error error) {
        if(this.erros == null){
            this.erros = new ArrayList<Error>();
        }
        this.erros.add(error);
    }

    public void addErros(String key, String message) {
        if(this.erros == null){
            this.erros = new ArrayList<Error>();
        }
        this.erros.add(new Error(key, message));
    }

    public boolean hasErrors() {
        if(this.erros == null){
            this.erros = new ArrayList<Error>();
        }
        if (this.erros.size() > 0) {
            return true;
        } else {
            return false;
        }
    }

    public void clear() {
        this.erros = new ArrayList<Error>();
    }

    /**
     * @return the erros
     */
    public List<Error> getErros() {
        List<Error> listErros = new ArrayList<Error>();
        listErros.addAll(erros);
        clear();
        return listErros;
    }

    /**
     * @param erros the erros to set
     */
    public void setErros(List<Error> erros) {
        this.erros = erros;
    }
}
